package com.siyoumi.app.test.sys;

import com.siyoumi.app.config.ThreadPoolConfig;
import com.siyoumi.app.test.sys.entity.TestThread;
import com.siyoumi.app.test.sys.entity.TestThreadCall;
import com.siyoumi.component.XApp;
import com.siyoumi.test.TestController;
import com.siyoumi.test.annotation.TestClass;
import com.siyoumi.test.annotation.TestFunc;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.entity.ThreadLocalData;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//线程相关
@TestClass(
        //runMethods = {"testThread", "testThread02", "testThreadJoin"}
        runMethods = {"testPool"}
)
@Slf4j
@RestController
@RequestMapping("/test/test_thread")
public class testThread
        extends TestController {
    private Lock lock = new ReentrantLock();

    @TestFunc("Lock用法")
    public XReturn testLock() {
        boolean tryLock = lock.tryLock(); //非阻塞，尝试加锁
        lock.lock(); //加锁
        lock.unlock(); //解锁

        XReturn r = XReturn.getR(0);
        r.setData("try_lock", tryLock);
        return r;
    }

    @TestFunc("ThreadLocal用法")
    public XReturn testThreadLocal() {
        ThreadLocal<String> threadLocal = new ThreadLocal<>();
        threadLocal.set("aaa");

        Thread thread = Thread.currentThread();

        String s = threadLocal.get();

        XReturn r = XReturn.getR(0);
        r.setData("s", s);
        r.setData("t_name", thread.getName());
        r.setData("t_id", thread.getId());

        return r;
    }


    private String s = "lock";

    @TestFunc("测试Synchronized")
    public XReturn testSynchronized() {
        synchronized (s) {
        }
        return XReturn.getR(0);
    }


    @TestFunc("开启绑定方法01")
    public XReturn testThread() {
        Thread thread = new Thread(new TestThread());
        thread.start();

        return XReturn.getR(0);
    }

    @TestFunc("开启绑定方法02")
    public XReturn testThread02() {
        Thread thread = new Thread(() -> {
            log.debug("02:{}", XDate.toDateTimeString());
        });
        thread.start();

        return XReturn.getR(0);
    }

    @SneakyThrows
    @TestFunc("开启绑定方法03")
    public XReturn testThread03() {
        //可以有返回值
        FutureTask<String> futureTask = new FutureTask<>(new TestThreadCall());
        Thread thread = new Thread(futureTask);
        thread.start();

        String result = futureTask.get();
        XReturn r = XReturn.getR(0);
        r.setData("result", result);

        return r;
    }

    @SneakyThrows
    @TestFunc("控制线程的执行顺序")
    public XReturn testThreadJoin() {
        XReturn r = XReturn.getR(0);


        Thread thread1 = new Thread(() -> {
            log.debug("线程1");

            Thread thread3 = new Thread(() -> {
                log.debug("线程3");
            });
            thread3.start();
            try {
                thread3.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread thread2 = new Thread(() -> {
            log.debug("线程2");
        });
        thread1.start();
        thread1.join();
        thread2.start();


        return r;
    }

    @SneakyThrows
    @TestFunc("completeFuture的使用")
    public XReturn testCompleteFuture() {
        XReturn r = XReturn.getR(0);

        CompletableFuture<String> test = CompletableFuture.supplyAsync(() -> {
            log.debug("有返回值，异常任务");
            return "test";
        });
        r.setData("test", test.get());

        CompletableFuture.runAsync(() -> {
            XApp.sleep(2);
            log.debug("无返回值，异常任务01");
        });
        CompletableFuture.runAsync(() -> {
            log.debug("无返回值，异常任务02");
        });

        return r;
    }

    @SneakyThrows
    @TestFunc("测试线程池")
    public XReturn testPool() {
        XReturn r = XReturn.getR(0);

        String id = XApp.shortId();
        ThreadLocalData.set("id", id);
        log.info("id: {}", id);

        Thread thread = new Thread(() -> {
            String i = ThreadLocalData.get("id", "");
            log.debug("Thread: {}-{}", i, XDate.toDateTimeString());
            XApp.sleep(3);
        });

        //ExecutorService executorService = Executors.newFixedThreadPool(3);
        //executorService.submit(thread);
        //executorService.submit(thread);
        //executorService.submit(thread);
        //executorService.submit(thread);


        ThreadPoolTaskExecutor threadPoolExecutor = ThreadPoolConfig.getIns().threadPools();
        //ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        //        1,  // 核心线程数量
        //        1,              //最大线程数
        //        5,             //空闲临时线程最大存活时间（数值）
        //        TimeUnit.SECONDS,//空闲临时线程最大存活时间（单位）
        //        new ArrayBlockingQueue<>(1),//任务队列，也就是一个堵塞队列，也可以使用LinkedBlockingQueue这个阻塞队列
        //        Executors.defaultThreadFactory(),//用线程池工具类Executors创建线程的工厂
        //        new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略中其中一个，丢弃任务并抛出RejectedExecutionException
        //);
        threadPoolExecutor.submit(thread);
        threadPoolExecutor.submit(thread);
        threadPoolExecutor.submit(thread);
        threadPoolExecutor.submit(thread);


        return r;
    }
}
